package com.dsy.utils;

import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizer;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerListener;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerResponse;
import com.dsy.ControllerApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.locks.LockSupport;

public class ConvertUtils {


    private static final Logger logger = LoggerFactory.getLogger(ControllerApplication.class);
    private static final String appKey = "fMnnonJCIEhqvLBN";
    private static final String accessKeySecret = "znBJ6uRJP54kJU3x0pZpSxY3aT4Duh";
    private static final String accessKeyID = "LTAI5tPCo4zpAx4T8rEmaLNt";


    public static int getSleepDelta(int dataSize, int sampleRate) {
        // 仅支持16位采样。
        int sampleBytes = 16;
        // 仅支持单通道。
        int soundChannel = 1;
        return (dataSize * 10 * 8000) / (160 * sampleRate);
    }

    public static String convert(String filepath, int sampleRate) throws Exception {
        SpeechRecognizer recognizer = null;
        final String[] result = {""};
        //传递用户自定义参数
        try {
            AccessToken accessToken = new AccessToken(accessKeyID, accessKeySecret);
            accessToken.apply();
            String tokenToken = accessToken.getToken();
            NlsClient client = new NlsClient("wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1", tokenToken);
            SpeechRecognizerListener listener = new SpeechRecognizerListener() {
                //识别出中间结果。仅当setEnableIntermediateResult为true时，才会返回该消息。
                @Override
                public void onRecognitionResultChanged(SpeechRecognizerResponse response) {
                    logger.info("text: " + response.getRecognizedText() + "   status: " + response.getStatusText());
                }

                //识别完毕
                @Override
                public void onRecognitionCompleted(SpeechRecognizerResponse response) {
                    result[0] = response.getRecognizedText();
                    logger.info("status: {}，statusText：{}，responseText；{}", response.getStatus(), response.getStatusText(), response.getRecognizedText());
                }

                @Override
                public void onStarted(SpeechRecognizerResponse response) {
                    logger.info("status: {}，statusText：{}", response.getStatus(), response.getStatusText());
                }

                @Override
                public void onFail(SpeechRecognizerResponse response) {
                    logger.info("status: {}，statusText：{}", response.getStatus(), response.getStatusText());
                }
            };
            recognizer = new SpeechRecognizer(client, listener);
            recognizer.setAppKey(appKey);
            //设置音频编码格式。如果是OPUS文件，请设置为InputFormatEnum.OPUS。
            recognizer.setFormat(InputFormatEnum.WAV);
            //设置音频采样率
            if (sampleRate == 16000) {
                recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
            } else if (sampleRate == 8000) {
                recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_8K);
            }
            //设置是否返回中间识别结果
            recognizer.setEnableIntermediateResult(true);
            //设置是否打开语音检测（即vad）
            recognizer.addCustomedParam("enable_voice_detection", true);
            //此方法将以上参数设置序列化为JSON发送给服务端，并等待服务端确认。
            long now = System.currentTimeMillis();
            recognizer.start();
            logger.info("ASR start latency : " + (System.currentTimeMillis() - now) + " ms");
            File file = new File(filepath);
            FileInputStream fis = new FileInputStream(file);
            byte[] b = new byte[3200];
            int len;
            while ((len = fis.read(b)) > 0) {
                logger.info("send data pack length: " + len);
                recognizer.send(b, len);
                //本案例用读取本地文件的形式模拟实时获取语音流，因为读取速度较快，这里需要设置sleep时长。
                // 如果实时获取语音则无需设置sleep时长，如果是8k采样率语音第二个参数设置为8000。
                int deltaSleep = getSleepDelta(len, sampleRate);
                LockSupport.parkNanos((long) deltaSleep * 1000 * 1000);
            }
            //通知服务端语音数据发送完毕，等待服务端处理完成。
            now = System.currentTimeMillis();
            //计算实际延迟，调用stop返回之后一般即是识别结果返回时间。
            logger.info("ASR wait for complete");

            recognizer.stop();
            logger.info("ASR stop latency : " + (System.currentTimeMillis() - now) + " ms");
            fis.close();

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //关闭连接
            if (null != recognizer) {
                recognizer.close();

            }
        }
        return result[0];
    }
}
